home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr15
/
ascgif20.zip
/
ASCGIF20.C
next >
Wrap
C/C++ Source or Header
|
1992-12-28
|
18KB
|
645 lines
/*
* Ascii Gif Viewer Version 2.0 Dec (c) 1992 John Ferrell
* jwf10@juts.ccc.amdahl.com Freeware. Public Domain.
* Shows gif pictures using text characters.
*/
/* 7 changes for pc to mainframe portability. (search on 'mainframes') */
/* some mini/workstations might need some of the pc definitions */
#include <string.h>
#include <stdlib.h> /* libc.h for mainframes, stdlib.h for pc */
#include <stdio.h>
#include <malloc.h> /* malloc.h may not be needed with some mainframes */
#define UBYTE unsigned char /* 8Bit */
#define UWORD unsigned short /* 16Bit */
#define ULONG unsigned long /* 32Bit int for mainframes, long for pc */
#define BOOL unsigned short
#define TRUE 1
#define FALSE 0
struct GIFdescriptor {
UWORD gd_Width;
UWORD gd_Height;
UBYTE gd_ColInfo;
UBYTE gd_BackGround;
UBYTE gd_PixelAspect;
};
struct ImageDesc {
UWORD id_Left;
UWORD id_Top;
UWORD id_Width;
UWORD id_Height;
UBYTE id_Info;
};
struct RGB {
UBYTE rgb_Red;
UBYTE rgb_Green;
UBYTE rgb_Blue;
};
#define GIF_IMAGE 0x2C
#define GIF_EXTENSION 0x21
#define GIF_TERMINATOR 0x3B
#define GIF_COMMENT_EXT 0xFE
void *screen; /* uncomment for pc, comment out for
* mainframes */
struct GIFdescriptor gdesc;
UBYTE **BitPlane;
struct RGB GlobalColourTable[256];
UBYTE Map[256];
ULONG ImageNumber;
FILE *GIFfh = NULL;
FILE *CAPT = NULL;
void
ERROR(str)
char *str;
{
printf(str);
exit(1);
}
void
FlipWord(word)
UWORD *word;
{
UBYTE swap1;
UBYTE swap2;
/* swap1 = *word & 0xFF; */ /* comment out for pc, needed for mainframes */
/* swap2 = (*word & 0xFF00) >> 8; */ /* " " */
/* *word = swap1 << 8 | swap2; */ /* " " */
}
static struct ImageDesc idesc;
static struct RGB LocalColourTable[256];
static UWORD Xpos, Ypos;
static BOOL interleave;
static UBYTE LeaveStep[5] = {1, 8, 8, 4, 2};
static UBYTE LeaveFirst[5] = {0, 0, 4, 2, 1};
static int ReadError;
static UBYTE CodeSize;
static int EOFCode;
static UBYTE ReadMask;
static int CompDataPointer;
static int CompDataCount;
static UBYTE CompData[256];
static UWORD Prefix[4096];
static UBYTE Suffix[4096];
static UBYTE OutCode[1025];
static UBYTE ByteBuf;
int
ReadCode(fh)
FILE *fh;
{
register int temp;
register int DstMasked;
register int DstMask;
long size;
temp = 0;
DstMasked = 1L << CodeSize;
for (DstMask = 1; DstMask != DstMasked; DstMask <<= 1) {
if (!ReadMask) {
if (CompDataPointer == CompDataCount) {
if ((size = fgetc(fh)) == -1) {
printf("\nI/O Error during decompression.\n");
ReadError = 1;
return EOFCode;
}
if (fread((char *) CompData, 1, size, fh) != size) {
printf("\nI/O Error during decompression.\n");
ReadError = 1;
return EOFCode;
}
CompDataCount = size;
CompDataPointer = 0;
}
ReadMask = 1;
ByteBuf = CompData[CompDataPointer++];
}
if (ByteBuf & ReadMask)
temp |= DstMask;
ReadMask <<= 1;
}
return temp;
}
void
AddPixel(index)
UBYTE index;
{
register UWORD XStore;
register UWORD YStore;
XStore = Xpos + idesc.id_Left;
YStore = Ypos + idesc.id_Top;
BitPlane[YStore][XStore] = index;
if (++Xpos == idesc.id_Width) {
Xpos = 0;
Ypos += LeaveStep[interleave];
if (Ypos >= idesc.id_Height)
Ypos = LeaveFirst[++interleave];
}
}
BOOL
DoImage(fh)
FILE *fh;
{
register int index;
register int colours;
int Code;
printf("Image #%ld encountered.\n", ImageNumber++);
if (fread((char *) &idesc, 1, 9, fh) != 9)
ERROR("Error reading image descriptor.\n");
FlipWord(&idesc.id_Left);
FlipWord(&idesc.id_Top);
FlipWord(&idesc.id_Width);
FlipWord(&idesc.id_Height);
interleave = idesc.id_Info & 1L << 6;
if (interleave)
interleave = 1;
printf("Xpos from %d to %d, Ypos from %d to %d, %sinterlaced.\n",
idesc.id_Left, idesc.id_Left + idesc.id_Width - 1,
idesc.id_Top, idesc.id_Top + idesc.id_Height - 1,
interleave ? "" : "not ");
if (idesc.id_Info & 1L << 7) {
colours = 1L << ((idesc.id_Info & 7) + 1);
printf("Local colour map contains %d entries.\n", colours);
for (index = 0; index < colours; index++)
if (fread(&LocalColourTable[index], 1, 3, fh) != 3)
ERROR("......Error reading local colour\n");
} else {
colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
for (index = 0; index < colours; index++)
LocalColourTable[index] = GlobalColourTable[index];
}
Xpos = Ypos = 0;
{
int MaxCode, ClearCode, CurCode, OldCode, InCode, FreeCode;
int OutCount;
int FirstFree;
UBYTE InitCodeSize, FinChar, BitMask;
if ((CodeSize = fgetc(fh)) == -1)
ERROR("\n......I/O Error during decompression.\n");
ClearCode = 1L << CodeSize;
EOFCode = ClearCode + 1;
FreeCode = FirstFree = ClearCode + 2;
CodeSize++;
InitCodeSize = CodeSize;
MaxCode = 1L << CodeSize;
ReadError = ReadMask = OutCount = 0;
CompDataPointer = CompDataCount = 0;
BitMask = colours - 1;
Code = ReadCode(fh);
while (Code != EOFCode) {
if (ReadError)
return TRUE;
if (Code == ClearCode) {
CodeSize = InitCodeSize;
MaxCode = 1L << CodeSize;
FreeCode = FirstFree;
FinChar = CurCode = OldCode = Code = ReadCode(fh);
AddPixel(FinChar);
} else {
CurCode = InCode = Code;
if (CurCode >= FreeCode) {
CurCode = OldCode;
OutCode[OutCount++] = FinChar;
}
while (CurCode > BitMask) {
if (OutCount > 1024) {
printf("\nCorrupt GIF file (OutCount)\n");
return TRUE;
}
OutCode[OutCount++] = Suffix[CurCode];
CurCode = Prefix[CurCode];
}
FinChar = CurCode;
AddPixel(FinChar);
for (index = OutCount - 1; index >= 0; index--)
AddPixel(OutCode[index]);
OutCount = 0;
Prefix[FreeCode] = OldCode;
Suffix[FreeCode] = FinChar;
OldCode = InCode;
if (++FreeCode >= MaxCode) {
if (CodeSize < 12) {
CodeSize++;
MaxCode <<= 1;
}
}
}
Code = ReadCode(fh);
}
}
if ((Code = fgetc(fh)) == -1)
return TRUE;
if (Code != 0)
printf("Warning: Unaligned packet.\n");
return FALSE;
}
#define base 0
int gx = 79;
int gy = 24;
int bg = 1;
int max = 0;
#define clors 16
char *clortab[clors] =
{".", ",", ":", ";", "=", "+", "i", "t", "I", "Y", "V", "X", "R", "B", "M", "W"};
char *invcltab[clors] =
{"W", "M", "B", "R", "X", "V", "Y", "I", "t", "i", "+", "=", ";", ":", ",", "."};
void
show(name)
char *name;
{
int x, y, j, i;
int ix, iy, ii, jj;
struct RGB colour;
char Cbuf[1];
long best, z;
int adj, top, bot, flag, cc, dx, dy, f, dcnt, inverse;
adj = x = y = ix = iy = dx = dy = i = j = z = dcnt = f = inverse = 0;
top = 0;
bot = 256;
cc = 1;
dx = 8;
dy = 16;
do {
if (!max)
if (adj && f){
flag = 'v';
adj = 0;
} else {
printf("\nAscgif20 (vi)ew (fF)ocus (zZ)oom (c)opy (l,r,u,d)=PAN (q)uit (h)elp: ");
while ((flag = getchar()) == (char) 10);
if (flag == 'v' || flag == 'z' || flag == 'Z' ||
flag == 'l' || flag == 'h' || flag == 'c' || flag == 'i' ||
flag == 'f' || flag == 'F' ||
flag == 'r' || flag == 'u' || flag == 'd' ||
flag == '1' || flag == '2' || flag == '3' || flag == '4');
else
return;
};
if (flag == 'v')
cc = 1;
if (flag == 'f'){
printf ("Adjusting focus...");
f = 1;
adj = 1;
top = 0;
bot = 256;
}
if (flag == 'F')
f = 0;
if (flag == 'i')
if (inverse == 1)
inverse = 0;
else
inverse = 1;
if (flag == '1') {
cc = 1;
printf("\nDefault Mix\n");
}
if (flag == '2') {
cc = 2;
printf("\nRed Mix Blocked\n");
}
if (flag == '3') {
cc = 3;
printf("\nGreen Mix Blocked\n");
}
if (flag == '4') {
cc = 4;
printf("\nBlue Mix Blocked\n");
}
if (flag == 'c') {
printf("\nAppending copy of screen to file ascgifs\n");
if (!(CAPT = fopen("ascgifs", "a")))
ERROR("Open error\n");
Cbuf[0] = 10;
if (fwrite(Cbuf, 1, 1, CAPT) != 1)
ERROR("Unable to write to ascgifs.\n");
if (fwrite(name, 1, strlen(name), CAPT) != strlen(name))
ERROR("Unable to write to ascgifs.\n");
}
if (flag == 'u') {
if (f){
printf ("Adjusting focus, Moving up...");
adj = 1;
top = 0;
bot = 256;
};
if (iy >= dy * gy / 6)
iy = iy - dy * gy / 6;
};
if (flag == 'd') {
if (f){
printf ("Adjusting focus, Moving down...");
adj = 1;
top = 0;
bot = 256;
};
if (iy + dy * gy + 2 * dy < ((idesc.id_Height) << base))
iy = iy + dy * gy / 6;
};
if (flag == 'z') {
if (f){
adj = 1;
top = 0;
bot = 256;
printf ("Adjusting focus, Zooming in...");
};
dx -= 1;
dy -= 2;
if (dx < 1)
dx = 1;
else
ix = ix + dx * gx / 8;
if (dy < 2)
dy = 2;
else
iy = iy + dy * gy / 8;
};
if (flag == 'Z') {
if (f){
adj = 1;
printf ("Adjusting focus, Zooming out...");
};
dx = 8;
dy = 16;
top = 0;
bot = 256;
ix = 0;
iy = 0;
};
if (flag == 'r') {
if (f){
printf ("Adjusting focus, Moving right...");
adj = 1;
top = 0;
bot = 256;
};
if (ix + dx * gx + 2 * dx < ((idesc.id_Width) << base))
ix = ix + dx * gx / 6;
};
if (flag == 'l') {
if (f){
printf ("Adjusting focus, Moving left...");
adj = 1;
top = 0;
bot = 256;
};
if (ix >= dx * gx / 6)
ix = ix - dx * gx / 6;
};
if (idesc.id_Width / gx < dx){
dx = idesc.id_Width / gx;
if (dx < 1) dx = 1;
}
if (idesc.id_Height / gy < dy){
dy = idesc.id_Height / gy;
if (dy < 1) dy = 1;
}
if (max){
gx = idesc.id_Width;
gy = idesc.id_Height;
dx = dy = 1;
}
y = iy;
if (flag == 'h') {
printf("\nascgif(2.0) use: ascgif it.gif <M> <output width> <output height>\n");
printf(" M shows to stdout with maximum dimensions\n");
printf(" M invalid with <output width> <output height>\n");
printf(" M Example: ascgif it.gif M >bigpic\n");
printf("v = View the Gif\n");
printf("i = Toggle inverse screen\n");
printf("f = Focus the screen\n");
printf("F = Fuzzy but fast. Good for positioning.\n");
printf("z = Zoom in on the center\n");
printf("Z = Zoom out to normal size\n");
printf("c = Capture screen\n");
printf("l = Pan Left\n");
printf("r = Pan Right\n");
printf("u = Pan Up\n");
printf("d = Pan Down\n");
printf("1 = Default Mix (in Fuzzy mode only)\n");
printf("2 = Red Mix Blocked (in Fuzzy mode only)\n");
printf("3 = Green Mix Blocked (in Fuzzy mode only)\n");
printf("4 = Blue Mix Blocked (in Fuzzy mode only)\n");
printf("Any other character will quit\n");
} else {
for (j = 0; j < gy; j++) {
if (flag == 'c') {
Cbuf[0] = 10;
if (fwrite(Cbuf, 1, 1, CAPT) != 1)
ERROR("Unable to write to ascgifs.\n");
}
if (!adj)
printf("\n");
x = ix;
for (i = 0; i < gx; i++) {
if (f) {
dcnt = 0;
best = 0;
for (jj = y; jj - y < dy; jj++) {
for (ii = x; ii - x < dx; ii++) {
colour = LocalColourTable[BitPlane[(jj >> base) + idesc.id_Top]
[(ii >> base) + idesc.id_Left]];
z = (colour.rgb_Red + colour.rgb_Green + colour.rgb_Blue) / 3;
dcnt++;
best = (best * (dcnt - 1) + z) / dcnt;
}
};
if (best < bot)
bot = best;
if (best > top)
top = best;
if (top != bot)
best = (best - bot) * 256 / (top - bot);
if (best >= 256)
best = 255;
if (best < 0)
best = bg;
if (!adj){
if (flag == 'c') {
if (inverse) {
Cbuf[0] = *invcltab[(best) * clors / 0x100];
if (fwrite(Cbuf, 1, 1, CAPT) != 1)
ERROR("Unable to write to ascgifs.\n");
} else {
Cbuf[0] = *clortab[(best) * clors / 0x100];
if (fwrite(Cbuf, 1, 1, CAPT) != 1)
ERROR("Unable to write to ascgifs.\n");
}
};
if (inverse)
printf(invcltab[(best) * clors / 0x100]);
else
printf(clortab[(best) * clors / 0x100]);
};
x += dx;
if (x > (idesc.id_Width << base))
break;
} else {
colour = LocalColourTable[BitPlane[(y >> base) + idesc.id_Top]
[(x >> base) + idesc.id_Left]];
if (cc == 2) {
z = (colour.rgb_Green + colour.rgb_Blue) / 2;
} else if (cc == 3) {
z = (colour.rgb_Red + colour.rgb_Blue) / 2;
} else if (cc == 4) {
z = (colour.rgb_Red + colour.rgb_Green) / 2;
} else {
z = (colour.rgb_Red + colour.rgb_Green + colour.rgb_Blue) / 3;
};
if (flag == 'c') {
if (inverse) {
Cbuf[0] = *invcltab[(z) * clors / 0x100];
if (fwrite(Cbuf, 1, 1, CAPT) != 1)
ERROR("Unable to write to ascgifs.\n");
} else {
Cbuf[0] = *clortab[(z) * clors / 0x100];
if (fwrite(Cbuf, 1, 1, CAPT) != 1)
ERROR("Unable to write to ascgifs.\n");
}
};
if (inverse)
printf(invcltab[(z) * clors / 0x100]);
else
printf(clortab[(z) * clors / 0x100]);
x += dx;
if (x > (idesc.id_Width << base))
break;
};
}
y += dy;
if (y > (idesc.id_Height << base))
break;
}
}
if (max)
return;
if (flag == 'c')
fclose(CAPT);
} while (TRUE);
}
main(argc, argv)
int argc;
char *argv[];
{
register int index;
char sig[7];
int size;
int error;
int colours;
long cmdcode;
if (argc < 2){
printf("ascgif(2.0) use: ascgif name.gif <M> <output width> <output height>\n");
printf(" M shows to stdout with maximum dimensions\n");
printf(" M invalid with <output width> <output height>\n");
ERROR(" M Example: ascgif it.gif M >bigpic\n");
}
if (!(GIFfh = fopen(argv[1],"rb")))
/* "rb" for pc, "r" for SOME mainframes */
ERROR("Open error\n");
if (argc > 2) {
if ('M' == *argv[2]){
max = 1;
} else {
if (!(gx = atoi(argv[2])))
ERROR("3rd parameter not numeric, (width)\n");
if (!(gy = atoi(argv[3])))
ERROR("4th parameter not numeric, (height)\n");
};
} else {
gx = 79;
gy = 24;
};
sig[6] = '\0';
if (fread(sig, 1, 6, GIFfh) != 6 || strcmp("GIF87a", sig))
ERROR("Not an 87a GIF file...\n");
if (fread((char *) &gdesc, 1, 7, GIFfh) != 7)
ERROR("Error reading screen descriptor\n");
FlipWord(&gdesc.gd_Width);
FlipWord(&gdesc.gd_Height);
printf("Ascgif Ver 2.0\n");
printf("Signature = \"%s\", Width = %u, Height = %u\n",
sig, gdesc.gd_Width, gdesc.gd_Height);
colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
if (!(gdesc.gd_ColInfo & 1L << 7)) {
printf("No global colour map supplied, using internal.\n");
for (index = 0; index < colours; index++) {
GlobalColourTable[index].rgb_Red =
GlobalColourTable[index].rgb_Green =
GlobalColourTable[index].rgb_Blue = index;
}
} else {
printf("Global colour map contains %d entries.\n", colours);
for (index = 0; index < colours; index++)
if (fread(&GlobalColourTable[index], 1, 3, GIFfh) != 3)
ERROR("Error reading global colour\n");
}
size = ((gdesc.gd_Width + 7) / 8) + 1;
size += (size + 127) >> 7; /* use far,_fmalloc for pc, not for mainframes */
if (!(BitPlane = (UBYTE far **) _fmalloc(gdesc.gd_Height * sizeof(UBYTE *))))
/* if (!(BitPlane = (UBYTE **) malloc(gdesc.gd_Height * sizeof(UBYTE *)))) */
ERROR("Not enough memory\n");
size = (gdesc.gd_Width + 1) * sizeof(UBYTE);
for (index = 0; index < gdesc.gd_Height; index++)
/* use far,_fmalloc for pc, not for mainframes */
if (!(BitPlane[index] = (UBYTE far *) _fmalloc(size)))
/* if (!(BitPlane[index] = (UBYTE *) malloc(size))) */
ERROR("Not enough memory\n");
ImageNumber = 1;
for (error = FALSE; error == FALSE;) {
if ((cmdcode = fgetc(GIFfh)) == -1)
break;
if (cmdcode ==
GIF_IMAGE) {
error = DoImage(GIFfh);
} else if (cmdcode ==
GIF_EXTENSION) {
error = TRUE;
} else if (cmdcode ==
GIF_TERMINATOR) {
show(argv[1]);
break;
} else {
printf("Unknown directive encountered.\n");
error = TRUE;
}
}
printf("End of GIF session\n");
return (0);
}